﻿using Nop.Core;
using Nop.Core.Domain.Common;
using Nop.Core.Domain.Customers;
using Nop.Core.Domain.Directory;
using Nop.Services.Common;
using Nop.Services.Customers;
using Nop.Services.Directory;
using Nop.Services.Logging;
using Nop.Services.Security;
using Nop.Web.Framework;
using Nop.Web.Framework.Kendoui;
using Nop.Web.Framework.Security.Captcha;
using Nop.Web.Models.Common;
using Nop.Web.Models.Security;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

namespace Nop.Web.Controllers
{
    public partial class CommonController : BasePublicController
    {
        #region Fields
        private readonly IPermissionAntService _permissionAntService;
        private readonly IWorkContext _workContext;
        private readonly IGenericAttributeService _genericAttributeService;
        private readonly ICustomerActivityService _customerActivityService;
        private readonly CommonSettings _commonSettings;
        private readonly CaptchaSettings _captchaSettings;
        private readonly ICustomerService _customerService;
        private readonly IRelatedEnumService _relatedEnumService;
        private readonly IDepartmentService _departmentService;
        private readonly IFlowService _flowService;
        private readonly IFlowStepsService _flowStepsService;
        #endregion

        #region Constructors

        public CommonController(IPermissionAntService permissionAntService,
            IWorkContext workContext,
            IGenericAttributeService genericAttributeService,
            ICustomerActivityService customerActivityService,
            CommonSettings commonSettings,
            CaptchaSettings captchaSettings,
            ICustomerService customerService,
            IRelatedEnumService relatedEnumService,
            IDepartmentService departmentService,
            IFlowService flowService,
            IFlowStepsService flowStepsService)
        {
            this._permissionAntService = permissionAntService;
            this._workContext = workContext;
            this._genericAttributeService = genericAttributeService;
            this._customerActivityService = customerActivityService;
            this._commonSettings = commonSettings;
            this._captchaSettings = captchaSettings;
            this._customerService = customerService;
            this._relatedEnumService = relatedEnumService;
            this._departmentService = departmentService;
            this._flowService = flowService;
            this._flowStepsService = flowStepsService;
        }

        #endregion

        #region Utilities
        [NonAction]
        protected virtual DepartmentModel PrepareDepartmentModelForList(Department p)
        {
            return new DepartmentModel
            {
                key = p.Id,
                Name = p.Name,
                Abbr = p.Abbr,
                Active = p.Active,
            };
        }

        [NonAction]
        protected virtual FlowViewModel PrepareFlowModelForList(Flow f)
        {
            return new FlowViewModel
            {
                key = f.Id,
                Name = f.Name,
            };
        }

        [NonAction]
        protected virtual MenuModel PrepareDepartMenuModelForList(Department d, List<Customer> customers)
        {
            return new MenuModel
            {
                key = string.Format("depart{0}", d.Id),
                value = string.Format("depart{0}", d.Id),
                title = d.Name,
                children = customers.Select(PrepareDepartMenuModelForList).ToList()
            };
        }
        [NonAction]
        protected virtual MenuModel PrepareDepartMenuModelForList(Customer c)
        {
            return new MenuModel
            {
                key = c.Id.ToString(),
                value = c.Id.ToString(),
                title = c.TrueName ?? c.Username
            };
        }

        [NonAction]
        protected virtual RelatedViewModel PrepareRelatedModelForList(RelatedEnum p, IList<RelatedEnum> relateds, string parentName = "")
        {
            var relatedChilds = relateds.Where(m => m.ParentId == p.Id);
            return new RelatedViewModel
            {
                key = p.Id,
                No = p.No,
                Name = p.Name,
                ParentId = p.ParentId,
                ParentName = parentName,
                Active = p.Active,
                IsSystem = p.IsSystem,
                DisplayOrder = p.DisplayOrder,
                children = relatedChilds.Any() ? relatedChilds.Select(x => PrepareRelatedModelForList(x, relateds, p.Name)).ToList() : null
            };
        }
        /// <summary>
        /// 类型树
        /// </summary>
        /// <param name="p"></param>
        /// <param name="allowSelectParent">允许选择父节点</param>
        /// <returns></returns>
        [NonAction]
        protected virtual MenuModel PrepareRelatedMenuModelForList(RelatedEnum p, IList<RelatedEnum> relateds, bool allowSelectParent = false)
        {
            var relatedChilds = relateds.Where(m => m.ParentId == p.Id);
            return new MenuModel
            {
                key = p.Id.ToString(),
                value = p.Id.ToString(),
                title = p.Name,
                selectable = allowSelectParent || !relatedChilds.Any(),
                children = relateds.Any() ? relatedChilds.Select(x => PrepareRelatedMenuModelForList(x, relateds, allowSelectParent)).ToList() : null
            };
        }
        #endregion

        #region Methods

        //page not found
        public virtual ActionResult PageNotFound()
        {
            this.Response.StatusCode = 404;
            this.Response.TrySkipIisCustomErrors = true;
            this.Response.ContentType = "text/html";

            return View();
        }

        public virtual ActionResult GenericUrl()
        {
            //seems that no entity was found
            return InvokeHttp404();
        }

        /// <summary>
        /// 图形验证码
        /// </summary>
        /// <param name="height"></param>
        /// <returns></returns>
        [PublicStoreAllowNavigation(true)]
        public ActionResult GenerateCaptcha(int height = 30)
        {
            CommonHelper.SetResponseNoCache(Response);
            this.Session["CaptchaImageText"] = CommonHelper.GenerateRandomCode(4).ToLower();
            Captcha ci = new Captcha(this.Session["CaptchaImageText"].ToString(), (int)Math.Ceiling((4 * 18.0)), height, "Arial");
            this.Response.Clear();
            this.Response.ContentType = "image/jpeg";
            byte[] bytes = ci.ImageByte;
            return File(bytes, @"image/jpeg");
        }

        #region 消息

        /// <summary>
        /// 待办事项
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        public JsonResult GetNotices(string guid)
        {
            var model = new List<NoticeModel>();
            return Json(model, JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// 流转事项
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        public JsonResult GetMessages(string guid)
        {
            var model = new List<NoticeModel>();
            return Json(model, JsonRequestBehavior.AllowGet);
        }

        public JsonResult GetProjectNotice()
        {
            var model = new List<ProjectNoticeModel>();
            model.Add(new ProjectNoticeModel
            {
                id = "001",
                title = "Alipay",
                logo = "https://gw.alipayobjects.com/zos/rmsportal/dURIMkkrRFpPgTuzkwnB.png",
                href = "",
                description = "那是一种内在的东西",
                member = "第一小组",
                memberLink = "",
                updatedAt = DateTime.Now
            });
            return Json(model, JsonRequestBehavior.AllowGet);
        }

        public class ProjectNoticeModel
        {
            public string id { get; set; }
            public string title { get; set; }
            public string href { get; set; }
            public string logo { get; set; }
            public string description { get; set; }
            public string member { get; set; }
            public string memberLink { get; set; }
            public DateTime updatedAt { get; set; }
        }
        #endregion

        #region 部门
        /// <summary>
        /// 部门列表
        /// </summary>
        /// <param name="model"></param>
        /// <param name="guid"></param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult DepartmentList(DepartmentListModel model, string guid = "")
        {
            if (!_permissionAntService.Authorize(guid, (int)PermissionAntEnum.department))
                return Json(new { result = false, msg = "无权访问" });
            var projectType = _departmentService.GetAllDepartments().Where(m => string.IsNullOrEmpty(model.Name) || m.Name.Contains(model.Name));
            var gridModel = new DataSourceResultAnt
            {
                list = projectType.Select(PrepareDepartmentModelForList),
                pagination = null
            };
            return Json(new { result = true, gridModel });
        }

        /// <summary>
        /// 保存部门信息
        /// </summary>
        /// <param name="model"></param>
        /// <param name="guid"></param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult SaveDepartment(DepartmentModel model, string guid)
        {
            if (!_permissionAntService.Authorize(guid, (int)PermissionAntEnum.department))
                return Json(new { result = false, msg = "无权访问" });
            var customer = _customerService.GetCustomerByToken(guid);
            if (null != customer)
            {
                try
                {
                    if (model.key == 0)
                    {
                        var depart = new Department
                        {
                            Name = model.Name,
                            Abbr = model.Abbr,
                            Active = model.Active
                        };
                        _departmentService.InsertDepartment(depart);
                        //activity log
                        _customerActivityService.InsertActivity("AddNewDepartment", "新增部门 Id={0}", depart.Id);
                    }
                    else
                    {
                        var depart = _departmentService.GetDepartmentById(model.key);
                        if (null != depart)
                        {
                            depart.Name = model.Name;
                            depart.Abbr = model.Abbr;
                            depart.Active = model.Active;
                            _departmentService.UpdateDepartment(depart);
                            //activity log
                            _customerActivityService.InsertActivity("EditDepartment", "修改部门 Id={0}", depart.Id);
                        }
                    }
                    return Json(new { result = true });
                }
                catch (Exception ex)
                {
                    return Json(new { result = false, msg = ex.Message });
                }
            }
            else
                return Json(new { result = false, msg = "用户无效" });
        }

        /// <summary>
        /// 删除部门信息
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult DeleteDepartment(int[] key, string guid)
        {
            if (!_permissionAntService.Authorize(guid, (int)PermissionAntEnum.department))
                return Json(new { result = false, msg = "无权访问" });
            try
            {
                var customer = _customerService.GetCustomerByToken(guid);
                if (null != customer)
                {
                    foreach (var id in key)
                    {
                        var depart = _departmentService.GetDepartmentById(id);
                        if (null != depart)
                        {
                            depart.Deleted = true;
                            _departmentService.UpdateDepartment(depart);
                            //activity log
                            _customerActivityService.InsertActivity("DeleteDepartment", "删除部门 Id={0}", depart.Id);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                return Json(new { result = false, msg = ex.Message });
            }
            return Json(new { result = true });
        }
        #endregion

        #region 流程
        [HttpPost]
        public JsonResult FlowList(FlowListModel model, string guid = "")
        {
            if (!_permissionAntService.Authorize(guid, (int)PermissionAntEnum.flow))
                return Json(new { result = false, msg = "无权访问" });
            var flows = _flowService.GetAllFlows();
            if (!string.IsNullOrEmpty(model.Name))
                flows = flows.Where(m => m.Name.Contains(model.Name)).ToList();
            var gridModel = new DataSourceResultAnt
            {
                list = flows.Select(PrepareFlowModelForList),
                pagination = null
            };
            return Json(new { result = true, gridModel });
        }

        /// <summary>
        /// 列表筛选条件
        /// </summary>
        /// <returns></returns>
        public JsonResult FlowFilter()
        {
            var model = new FlowListModel();

            var departments = _departmentService.GetAllDepartments();
            var customers = _customerService.GetAllCustomers(customerRoleIds: new[] { _customerService.GetCustomerRoleBySystemName(SystemCustomerRoleNames.Registered).Id });
            model.Customers = departments.Select(x => PrepareDepartMenuModelForList(x, customers.Where(m => m.DepartmentId == x.Id).ToList())).ToList();
            model.Customers.Add(new MenuModel
            {
                key = "depart0",
                value = "depart0",
                title = "无部门",
                children = customers.Where(m => m.DepartmentId == 0).Select(PrepareDepartMenuModelForList).ToList()
            });

            return Json(model, JsonRequestBehavior.AllowGet);
        }

        [HttpPost]
        public JsonResult GetFlow(int id = 0)
        {
            var model = new FlowModel();
            if (id > 0)
            {
                var flow = _flowService.GetFlowById(id);
                if (null != flow)
                {
                    model.key = flow.Id;
                    model.Name = flow.Name;
                    var steps = _flowStepsService.GetAllFlowStepss().Where(m => m.FlowId == id).ToList();
                    foreach (var step in steps)
                    {
                        model.FlowSteps.Add(new FlowStepsModel
                        {
                            key = step.Id,
                            Name = step.Name,
                            CustomerIds = step.Customers.Select(x => x.Id).ToArray()
                        });
                    }
                }
            }
            return Json(new { result = true, model });
        }

        /// <summary>
        /// 保存项目属地信息
        /// </summary>
        /// <param name="model"></param>
        /// <param name="guid"></param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult SaveFlow(FlowModel model, string guid)
        {
            if (!_permissionAntService.Authorize(guid, (int)PermissionAntEnum.flow))
                return Json(new { result = false, msg = "无权访问" });
            var customer = _customerService.GetCustomerByToken(guid);
            if (null != customer)
            {
                try
                {
                    if (model.key > 0)
                    {
                        var flow = _flowService.GetFlowById(model.key);
                        if (null != flow)
                        {
                            flow.Name = model.Name;
                            _flowService.UpdateFlow(flow);
                            #region 步骤
                            var steps = _flowStepsService.GetAllFlowStepss().Where(m => m.FlowId == flow.Id).ToList();
                            if (steps.Count == 0)
                            {
                                if (model.FlowSteps.Count > 0)
                                {
                                    foreach (var item in model.FlowSteps)
                                    {
                                        var step = new FlowSteps
                                        {
                                            FlowId = flow.Id,
                                            Name = item.Name
                                        };
                                        var customers = _customerService.GetCustomersByIds(item.CustomerIds);
                                        foreach (var c in customers)
                                        {
                                            if (!step.Customers.Contains(c))
                                                step.Customers.Add(c);
                                        }
                                        _flowStepsService.InsertFlowSteps(step);
                                    }
                                }
                            }
                            else
                            {
                                foreach (var step in steps.Where(m => !model.FlowSteps.Select(x => x.key).Contains(m.Id)).ToList())
                                {
                                    _flowStepsService.DeleteFlowSteps(step);
                                }
                                if (model.FlowSteps.Count > 0)
                                {
                                    foreach (var item in model.FlowSteps)
                                    {
                                        var step = _flowStepsService.GetFlowStepsById(item.key);
                                        if (null == step)
                                        {
                                            step = new FlowSteps
                                            {
                                                FlowId = flow.Id,
                                                Name = item.Name
                                            };
                                            var customers = _customerService.GetCustomersByIds(item.CustomerIds);
                                            foreach (var c in customers)
                                            {
                                                if (!step.Customers.Contains(c))
                                                    step.Customers.Add(c);
                                            }
                                            _flowStepsService.InsertFlowSteps(step);
                                        }
                                        else
                                        {
                                            step.Name = item.Name;
                                            if (item.CustomerIds == null || item.CustomerIds.Length == 0)
                                            {
                                                step.Customers.Clear();
                                                _flowStepsService.UpdateFlowSteps(step);
                                            }
                                            else
                                            {
                                                var removeCustomers = step.Customers.Where(m => !item.CustomerIds.Contains(m.Id)).ToList();
                                                if (removeCustomers.Any())
                                                {
                                                    for (int i = 0; i < removeCustomers.Count(); i++)
                                                    {
                                                        step.Customers.Remove(removeCustomers[i]);
                                                    }
                                                }
                                                var customers = _customerService.GetCustomersByIds(item.CustomerIds);
                                                foreach (var c in customers)
                                                {
                                                    if (!step.Customers.Contains(c))
                                                    {
                                                        step.Customers.Add(c);
                                                    }
                                                }
                                                _flowStepsService.UpdateFlowSteps(step);
                                            }
                                        }
                                    }
                                }
                            }
                            #endregion
                            //activity log
                            _customerActivityService.InsertActivity("EditFlow", "修改流程 Id={0}", flow.Id);
                        }
                    }
                    return Json(new { result = true });
                }
                catch (Exception ex)
                {
                    return Json(new { result = false, msg = ex.Message });
                }
            }
            else
                return Json(new { result = false, msg = "用户无效" });
        }
        #endregion

        #endregion
    }
}
